package com.lhz.project.system.service.auth.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lhz.common.constant.DataStatusEnum;
import com.lhz.common.page.BaseQueryParam;
import com.lhz.common.page.NewPageBean;
import com.lhz.framework.security.HolderInfoManager;
import com.lhz.project.system.mapper.auth.RoleDeptMapper;
import com.lhz.project.system.mapper.auth.RoleMapper;
import com.lhz.project.system.mapper.auth.RoleMenuMapper;
import com.lhz.project.system.model.entity.auth.Role;
import com.lhz.project.system.model.entity.auth.RoleDept;
import com.lhz.project.system.model.entity.auth.RoleMenu;
import com.lhz.project.system.model.param.auth.RoleParam;
import com.lhz.project.system.model.vo.auth.MenuTreeVo;
import com.lhz.project.system.model.vo.auth.RoleDeptVo;
import com.lhz.project.system.model.vo.auth.RoleMenuVo;
import com.lhz.project.system.model.vo.dept.DeptTreeVo;
import com.lhz.project.system.service.auth.MenuService;
import com.lhz.project.system.service.auth.RoleService;
import com.lhz.project.system.service.dept.DeptService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author LiHuaZhi
 * @since 2020-06-20 13:42:57
 */
@Service

public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Resource
    private RoleMapper roleMapper;

    @Resource
    private RoleMenuMapper roleMenuMapper;

    @Resource
    private RoleDeptMapper roleDeptMapper;

    @Resource
    private MenuService menuService;

    @Resource
    private DeptService deptService;

    @Override
    public Role selectByPrimaryKey(Integer id) {
        return roleMapper.selectByPrimaryKey(id);
    }

    @Override
    public Object listRole(BaseQueryParam param) {
        return NewPageBean.generatePage(() -> roleMapper.listRole(param), param, Role.class);
    }

    @Override
    @Transactional
    public void insert(RoleParam param) {
        String userId = HolderInfoManager.getUserId();

        //验证编码及名称是否重复
        checkNameAndCode(param);

        //插入角色信息
        Role role = new Role();
        BeanUtils.copyProperties(param, role);
        role.setOperate(DataStatusEnum.VALID.getCode());
        role.setStatus(DataStatusEnum.VALID.getCode());
        role.setDelFlag(DataStatusEnum.VALID.getCode());
        role.setCreateBy(userId);
        role.setUpdateBy(userId);
        roleMapper.insert(role);

        //插入角色菜单信息
        setRoleMenu(role.getId(), param.getMenuIds());
        //插入角色数据权限
        setRoleDept(role.getId(), param.getDeptIds());
    }

    @Override
    @Transactional
    public int updateByPrimaryKey(RoleParam param) {
        String userId = HolderInfoManager.getUserId();
        //验证编码及名称是否重复
        checkNameAndCode(param);

        //删除原来关联菜单
        roleMenuMapper.deleteRoleMenuByRoleId(param.getId());

        //删除原来关联部门
        roleDeptMapper.deleteRoleDeptByRoleId(param.getId());

        //重新插入信息
        //插入角色菜单信息
        setRoleMenu(param.getId(), param.getMenuIds());
        //插入角色数据权限
        setRoleDept(param.getId(), param.getDeptIds());

        //更新角色信息
        Role role = new Role();
        BeanUtils.copyProperties(param, role);

        role.setUpdateBy(userId);
        return roleMapper.updateById(role);
    }

    @Override
    @Transactional
    public int deletePhyByPrimaryKey(Integer id) {
        //删除关联数据
        //删除原来关联菜单
        roleMenuMapper.deleteRoleMenuByRoleId(id);

        //删除原来关联部门
        roleDeptMapper.deleteRoleDeptByRoleId(id);
        return roleMapper.deletePhyByPrimaryKey(id);
    }

    /**
     * 查询菜单信息
     *
     * @param id
     * @return
     */
    @Override
    public Object getRoleMenuById(Integer id) {
        //返回菜单树及角色已选菜单
        //查询菜单树
        List<MenuTreeVo> menu = menuService.selectTreeMenu();

        //查询关联菜单
        List<Integer> list = roleMenuMapper.selectMenuIdByRoleId(id);

        RoleMenuVo roleMenuVo = new RoleMenuVo();
        roleMenuVo.setMenuIds(list);
        roleMenuVo.setMenuTreeVo(menu);

        return roleMenuVo;
    }

    /**
     * 查询数据权限
     *
     * @param id
     * @return
     */
    @Override
    public Object getRoleDeptById(Integer id) {
        //返回部门树及角色已选菜单

        //查询角色数据范围
        Integer dataScope = roleMapper.selectByPrimaryKey(id).getDataScope();
        //查询部门树
        List<DeptTreeVo> dept = deptService.treeDept();
        //查询关联部门
        List<Integer> list = roleDeptMapper.selectDeptIdByRoleId(id);

        RoleDeptVo roleDeptVo = new RoleDeptVo();
        roleDeptVo.setDataScope(dataScope);
        roleDeptVo.setDeptIds(list);
        roleDeptVo.setDeptTreeVo(dept);

        return roleDeptVo;
    }

    private void setRoleMenu(Integer roleId, List<Integer> menuList) {
        List<RoleMenu> list = new ArrayList<>();
        for (Integer menuId : menuList) {
            RoleMenu rm = new RoleMenu();
            rm.setRoleId(roleId);
            rm.setMenuId(menuId);
            list.add(rm);
        }
        if (CollectionUtil.isNotEmpty(list)) {
            roleMenuMapper.insertBatch(list);
        }
    }

    private void setRoleDept(Integer roleId, List<Integer> deptList) {
        List<RoleDept> list = new ArrayList<>();
        for (Integer deptId : deptList) {
            RoleDept rd = new RoleDept();
            rd.setRoleId(roleId);
            rd.setDeptId(deptId);
            list.add(rd);
        }
        if (CollectionUtil.isNotEmpty(list)) {
            roleDeptMapper.insertBatch(list);
        }
    }

    /**
     * 验证编码及名称是否重复
     */
    private void checkNameAndCode(RoleParam param) {
        int count = roleMapper.checkNameAndCode(param);
        Assert.isFalse(count > 0, "菜单名称或编码重复");
    }
}